package biz

import (
	"context"
	"github.com/go-kratos/kratos/v2/errors"
	"github.com/go-kratos/kratos/v2/log"
	"github.com/google/uuid"
	//"github.com/google/uuid"
	"go_private_im/internal/logic/conf"
	//"strconv"
	"time"
)

type Token struct {
	UserId   int64   `json:"user_id"`  //用户 ID
	RoomId string  `json:"room_id"` //要进入的 群的ID ID
	Key string `json:"key"`     // 上一登录使用的key
	Platform string `json:"platform"`  //登录端的类型
	Accepts []int32 `json:"accepts"`  //可以接受哪些 群的消息
}

//请求
type ConnectReq struct {
	Token  *Token
	Server string
}

//返回
type ConnectRep struct {
	UserId int64
	RoomId string
	Key    string
	Accepts []int32
	Heartbeat int64
}

type DisconnectReq struct {
	UserId    int64  `json:"user_id"`
	Key    string `json:"key"`
	Server string
}
type Online struct {
	Server    string
	RoomCount map[string]int32
	Updated   int64
}

//用户
type User struct {
	Id int64
	Name string
	Token string
	Status int
	Type int
}

//房间 详情
type RoomDetailInfo struct {
	Id int64 `json:"id"`
	UserId int64 `json:"user_id"`
	RoomId string `json:"room_id"`
	Name string  `json:"name"`
	AddTime int64 `json:"add_time"`
	Type    int32 `json:"type"`
}



type RoomInfo struct {
	Id int64
	UserId int64
	Name string
	AddTime int64
	Announcement    string
	Intro string
	Status int32
}



type LogicRepo interface {

	//redis
	AddMapping(ctx context.Context,userId int64,key,server string)  error
	Disconnect(ctx context.Context, req *DisconnectReq) (bool, error)
	Heartbeat(ctx context.Context, req *DisconnectReq) error
	AddServerOnline(ctx context.Context, req *Online) (map[string]int32, error)
	KeysByUserIds(ctx context.Context, userIds []int64) (ress map[string]string, oldUserIds []int64, err error)
	ServersByKeys(ctx context.Context, keys []string) ([]string, error)

	//kafka
	PushMsg(ctx context.Context, op int32, server string, keys []string, msg []byte) error
	BroadcastRoomMsg(ctx context.Context, op int32, room string, msg []byte) error
	BroadcastMsg(ctx context.Context, op, speed int32, msg []byte) (err error)



	//消息持久化
	CreateRoomMsg(roomMsg *RoomMsg) error
	CreateRoomMsgs(roomMsg []*RoomMsg) error

	//通知 comet
	NotifyUserAddRoom(ctx context.Context,server string,keys []string,Room string)  error

	//数据操作
	RoomExist(ctx context.Context,roomId int64) (room *RoomDetailInfo,err error)
	UserOutRoom(ctx context.Context,server string,keys []string,Room string) error
	GetRoomDetail(ctx context.Context,roomId string,userId int64) (room *RoomDetailInfo,err error)
	GetRoomDetails(ctx context.Context,roomId string,userId []string) (roomInfo []*RoomDetailInfo,err error)
	GetUserAcceptsRooms (req *ConnectReq) (accepts []int32)
	GetUser(ctx context.Context,userId int64) (user *User, err error)
	GetUsers(ctx context.Context,userId []string) (users []*User, err error)
	AddRoomDetail(ctx context.Context,roomDetails []*RoomDetailInfo) error
	UserExistRoomDetail(ctx context.Context,roomId string,userId int64) bool
	DelRoomDetail(ctx context.Context,roomId string,userId int64) (err error)
	GetRoomsByUserId(ctx context.Context,userId int64) (roomInfo []*RoomInfo,err error)
	GetRoomDetailListByUserId(ctx context.Context,userId int64) (roomInfo []*RoomDetailInfo,err error)
	GetRoomsByRoomId(ctx context.Context,roomId string) (roomInfo RoomInfo,err error)
	GetRoomMsgs(roomId string) (roomMsg []*RoomMsg,err error)

	Login(ctx context.Context,user *LoginArg) (authToken *AuthToken,err error)
	LoginOut(ctx context.Context,user *LoginArg)  error
}

type LogicUsecase struct {
	conf *conf.Config
	repo LogicRepo
	log  *log.Helper
}

func NewLogicUsecase(conf *conf.Config, logger log.Logger, repo LogicRepo) *LogicUsecase {
	return &LogicUsecase{log: log.NewHelper(logger), repo: repo, conf: conf}
}

func (l *LogicUsecase) Connect(ctx context.Context, req *ConnectReq) (*ConnectRep, error) {
	key := l.GetKey(req.Token.Key)
	//验证 用户是否有权限进入该群聊
	if !l.RoomIdEqEmpty(req.Token.RoomId) {
		if !l.repo.UserExistRoomDetail(ctx,req.Token.RoomId,req.Token.UserId) {
			return nil, errors.NotFound("没有权限进入","没有权限进入")
		}
	}
	accepts := l.repo.GetUserAcceptsRooms(req)
	//判断状态
	err := l.repo.AddMapping(ctx, req.Token.UserId,key,req.Server)
	if err != nil {
		return nil, err
	}
	rep := &ConnectRep{}
	rep.Key = key
	rep.Accepts = accepts
	rep.RoomId = req.Token.RoomId
	rep.Heartbeat = int64(time.Second*320) * int64(2)
	return rep, nil
}

func (l *LogicUsecase) GetKey(key string) string {
	if  key == "" {
		key = uuid.New().String()
	}
	return key
}

func (l *LogicUsecase) RoomIdEqEmpty(room_id string) bool  {
	return room_id == ""
}

func (l *LogicUsecase) Disconnect(ctx context.Context, req *DisconnectReq) (bool, error) {
	return l.repo.Disconnect(ctx, req)
}

func (l *LogicUsecase) Heartbeat(ctx context.Context, req *DisconnectReq) error {
	return l.repo.Heartbeat(ctx, req)
}


func (l *LogicUsecase) RenewOnline(ctx context.Context, req *Online) (map[string]int32, error) {
	rommCount, err := l.repo.AddServerOnline(ctx, req)
	if err != nil {
		return nil, err
	}
	return rommCount, err
}
